#include"LinkedList.hpp"
#include<iostream>

//------------------------------------------
//function about listdata     --------------
//------------------------------------------

void ListData::init()
{
    std::cin>>a;
    std::cin>>b;
}

bool ListData::operator==(ListData& comData)
{
   if(this->a==comData.a&&this->b==comData.b)
   { 
        return 1;
   }
   else {
   return 0;
   }
}

void ListData::operator=(ListData* data)
{
   this->a=data->a;
   this->b=data->b;
}


void ListData::show()
{
    std::cout<<a<<" "<<b<<"\n";
}


//------------------------------------------
//function about linkedlist   --------------
//------------------------------------------

LinkedList::LinkedList()
{
    this->prior=this;
    this->next=this;
    this->length=0;
}


bool LinkedList::Ifempty()
{
    if(length==0)
    {
        return 1;
    }
    else 
    {
    return 0;
    }
}


LinkedList::~LinkedList()
{
    LinkedNode* tmp=this;
    LinkedNode* tmp2=this;
    for(int i=0;i<length;i++)
    {
        tmp=tmp->next;
        tmp2=tmp;
        delete tmp2;
    }
   
   delete this;
}

void LinkedList::ClearList()
{
    LinkedNode* tmp=this;
    LinkedNode* tmp2=this;
    for(int i=0;i<length;i++)
    {
        tmp=tmp->next;
        tmp2=tmp;
        delete tmp2;
    }

    this->prior=this;
    this->next=this;
    this->length=0;
}


int LinkedList::GetLength()
{
   return length;
}


ListData* LinkedList::GetElem(int location)
{
   //examine exception
    try{
    if(location>length||location<=0)
    {
        throw "GetElem location error!\n";
    }
    }catch(const char* msg)
    {
        std::cerr<<msg;
    }
   

    LinkedNode* tmp=this;
    for(int i=0;i<length;i++)
    {
       tmp=tmp->next;
    }
    
    return &(tmp->data);
}



ListData LinkedList::GetElemCpy(int location)
{
   //examine exception
    try{
    if(location>length||location<=0)
    {
      throw R"(GetElemCpy location error!
)";
    }
    }catch(const char* msg)
    {
        std::cerr<<msg;
    }
   

    LinkedNode* tmp=this;
    for(int i=0;i<length;i++)
    {
       tmp=tmp->next;
    }
    
    return tmp->data;

}


int LinkedList::FindElem(ListData& elem)
{
  LinkedNode* tmp=this;
    for(int i=0;i<length;i++)
    {
        tmp=tmp->next;
        if(tmp->data==elem)
        {
            return i;
        }
    }
    return 0; //don`t find equal elem


}  //return the location number in list.you can replace it by iterator in future



void LinkedList::Insert(ListData& elem,int location)
{
    //examine exception
    try{
    if(location>length||location<=0)
    {
        throw "Insert location error!\n";
    }
    }catch(const char* msg)
    {
        std::cerr<<msg;
    }

    //get the node at location
    LinkedNode* newElem=new LinkedNode;
    LinkedNode* tmp=this;
    for(int i=0;i<location;i++)
    {
        tmp=tmp->next;
    }

    //change data and pointer
    newElem->data=elem;
    newElem->next=tmp;
    newElem->prior=tmp->prior;

    newElem->prior->next=newElem;
    newElem->next->prior=newElem;

    length++;
}


void LinkedList::Delet(int location)
{
    //examine exception
    try{
    if(location>length||location<=0)
    {
        throw "Delet location error!\n";
    }
    }catch(const char* msg)
    {
        std::cerr<<msg;
    }


    LinkedNode* tmp=this;
    for(int i=0;i<location;i++)
    {
        tmp=tmp->next;
    }

    tmp->prior->next=tmp->next;
    tmp->next->prior=tmp->prior;

    delete tmp;
}


void LinkedList::PushBack(ListData& elem)
{
    LinkedNode* newNode=new LinkedNode;
    newNode->data=elem;     //copy data


    //chang pointer
    newNode->next=this;
    newNode->prior=this->prior;

    this->prior=newNode;
    newNode->prior->next=newNode;

    length++;
}


void LinkedList::PushFront(ListData& elem)
{
   LinkedNode* newNode=new LinkedNode;
   newNode->data=elem;         //copy data


   //chang pointer
//    if(length==0)             two case are equal  
//    {
//     this->next=newNode;
//     this->prior=newNode;

//     newNode->prior=this;
//     newNode->next=this;
//    }
//    else
//    {
     newNode->prior=this;
     newNode->next=this->next;

     this->next->prior=newNode;
     this->next=newNode;

//    }

     length++;
}
   

void LinkedList::ShowData()
{
  LinkedNode* tmp=this;
  for(int i=0;i<length;i++)
   {
    std::cout<<"the "<<i+1<<" data is:\n";
    tmp->next->data.show();
    tmp=tmp->next;
   }
}